home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C ++ / Frameworks / MacZoop 1.6.5 / Basic Classes / Z Sources / ZWindowManager.cpp < prev   
Encoding:
C/C++ Source or Header  |  1997-07-15  |  27.0 KB  |  1,140 lines  |  [TEXT/CWIE]

  1. /*************************************************************************************************
  2. *
  3. *
  4. *            ObjectMacZapp            -- a standard Mac OOP application template
  5. *
  6. *
  7. *
  8. *            ZWindowManager.cpp        -- desktop class handles floaters
  9. *
  10. *
  11. *
  12. *
  13. *
  14. *            © 1996, Graham Cox
  15. *
  16. *
  17. *
  18. *
  19. *************************************************************************************************/
  20.  
  21.  
  22. #include    "ZObjectArray.cpp"
  23.  
  24. #include    "MacZoop.h"
  25. #include    "ZWindow.h"
  26. #include    "ZDialog.h"
  27. #include    "ZEventHandler.h"
  28.  
  29.  
  30. ZWindowManager*        gWindowManager = NULL;
  31.  
  32.  
  33. /*--------------------------------***  CONSTRUCTOR  ***---------------------------------*/
  34.  
  35. ZWindowManager::ZWindowManager()
  36. {
  37.     // make the lists
  38.     
  39.     FailNIL( nonFloaters = new ZWindowList());
  40.     FailNIL( floaters = new ZWindowList());
  41.     
  42.     wmWindows = NULL;
  43.     wmMenu = NULL;
  44.     wmItemOffset = 0;
  45.     
  46.     // set up member for controlling window placement
  47.     
  48.     globalPlaceLoc.h = 2;
  49.     globalPlaceLoc.v = GetMBarHeight() + 2;
  50.     
  51.     // we are the only one, and we are global
  52.     
  53.     gWindowManager = this;
  54. }
  55.  
  56. /*---------------------------------***  DESTRUCTOR  ***---------------------------------*/
  57.  
  58.  
  59. ZWindowManager::~ZWindowManager()
  60. {
  61.     if ( nonFloaters )
  62.         ForgetObject( nonFloaters );
  63.         
  64.     if ( floaters )
  65.         ForgetObject( floaters );
  66.         
  67.     if ( wmWindows )
  68.         ForgetObject( wmWindows );
  69. }
  70.  
  71.  
  72. /*---------------------------------***  ADDWINDOW  ***----------------------------------*/
  73. /*    
  74. add the window to the relevant list of windows, and set its initial (Z) position
  75. ----------------------------------------------------------------------------------------*/
  76.  
  77. void    ZWindowManager::AddWindow( ZWindow* aWindow )
  78. {
  79.     FailNILParam( aWindow );
  80.     
  81.     // determine if this window is a floater or not:
  82.     
  83.     if ( aWindow->Floats())
  84.     {
  85.         ZWindow*    zw = GetBottomFloater();
  86.         
  87.         BringBehind( aWindow, zw );
  88.         floaters->AppendItem( aWindow );
  89.     }
  90.     else
  91.     {
  92.         SendBehind( aWindow->GetMacWindow(), NULL );
  93.         nonFloaters->AppendItem( aWindow );
  94.         
  95.         // if we're maintaining a "Windows" menu, append the window to our list if
  96.         // it non-floating and not a modal dialog box.
  97.         
  98.         Boolean        eligibleWindow;
  99.         
  100.         eligibleWindow = ( ! IsDialog( aWindow )) ||
  101.                             ( IsDialog( aWindow ) && ! ((ZDialog*) aWindow )->IsModal());
  102.         
  103.         if ( wmWindows && eligibleWindow )
  104.             wmWindows->AppendItem( aWindow );
  105.             
  106.         BuildWindowsMenu();
  107.     }    
  108. }
  109.  
  110.  
  111. /*--------------------------------***  REMOVEWINDOW  ***--------------------------------*/
  112. /*
  113. remove the window from the relevant list; make sure the next window is activated correctly.    
  114. ----------------------------------------------------------------------------------------*/
  115.  
  116. void    ZWindowManager::RemoveWindow( ZWindow* aWindow )
  117. {
  118.     FailNILParam( aWindow );
  119.     
  120.     ZWindow*    zw;
  121.     
  122.     if ( aWindow->Floats())
  123.     {
  124.         floaters->DeleteObject( aWindow );
  125.         
  126.         // next window in layer needs to be activated to maintain our list
  127.         
  128.         zw = GetTopFloater();
  129.         
  130.         if ( zw )
  131.             PostActivation( zw, TRUE );
  132.     }
  133.     else
  134.     {
  135.         nonFloaters->DeleteObject( aWindow );
  136.         
  137.         if ( wmWindows )
  138.             wmWindows->DeleteObject( aWindow );
  139.         
  140.         // next window in layer needs to be activated to maintain our list
  141.         
  142.         zw = GetTopWindow();
  143.         
  144.         if ( zw )
  145.             PostActivation( zw, TRUE );
  146.         
  147.         BuildWindowsMenu();
  148.         
  149.         // if all windows closed, reset global positioning variable
  150.         
  151.         if ( CountWindows() == 0 )
  152.         {
  153.             globalPlaceLoc.h = 2;
  154.             globalPlaceLoc.v = GetMBarHeight() + 2;
  155.         }
  156.     }
  157. }
  158.  
  159.  
  160. /*-------------------------------***  INITIALLYPLACE  ***-------------------------------*/
  161. /*
  162. Call this after creating a window to place it initially. By default, this will stack the
  163. windows from top left towards bottom right, taking into account their correct title bar
  164. heights, etc. Override for other behaviours. Floating windows are ignored by this method.    
  165. ----------------------------------------------------------------------------------------*/
  166.  
  167. void    ZWindowManager::InitiallyPlace( ZWindow* aWindow )
  168. {
  169.     Rect    wBorder;
  170.     short    gh, gv;
  171.     
  172.     FailNILParam( aWindow );
  173.     
  174.     if ( ! aWindow->Floats())
  175.     {
  176.         aWindow->GetStructureFrameBorder( &wBorder );
  177.         
  178.         gh = globalPlaceLoc.h + wBorder.left;
  179.         gv = globalPlaceLoc.v + wBorder.top;
  180.         
  181.         aWindow->PlaceAt( gh, gv );
  182.         
  183.         globalPlaceLoc.h += wBorder.left + 2;
  184.         globalPlaceLoc.v += wBorder.top + 2;
  185.     }
  186. }
  187.  
  188.  
  189. /*---------------------------------***  HIDEWINDOW  ***---------------------------------*/
  190. /*    
  191. make the window invisible to the user. Does not change its front-to-back ordering unless
  192. it was the top one in its layer, in which case the one below it is selected.
  193. ----------------------------------------------------------------------------------------*/
  194.  
  195. void    ZWindowManager::HideWindow( ZWindow* aWindow )
  196. {
  197.     FailNILParam( aWindow );
  198.     
  199.     ShowHide( aWindow->GetMacWindow(), FALSE );
  200.     HiliteWindow( aWindow->GetMacWindow(), FALSE );
  201.     
  202.     // if this was the top window, select the next none-hidden one
  203.     
  204.     if ( aWindow->Floats())
  205.     {
  206.         if ( aWindow == GetTopFloater() &&
  207.              floaters->CountItems() > 1 )
  208.         {
  209.             aWindow = floaters->GetObject( 2 );
  210.         
  211.             if ( aWindow && aWindow->IsVisible())
  212.                 SelectWindow( aWindow );
  213.         }
  214.     }
  215.     else
  216.     {
  217.         if ( aWindow == GetTopWindow() &&
  218.              nonFloaters->CountItems() > 1 )
  219.         {
  220.             aWindow = nonFloaters->GetObject( 2 );
  221.         
  222.             if ( aWindow && aWindow->IsVisible())
  223.                 SelectWindow( aWindow );
  224.         }
  225.     }
  226. }
  227.  
  228.  
  229. /*---------------------------------***  SHOWWINDOW  ***---------------------------------*/
  230. /*    
  231. make the window visible to the user. Does not change its front-to-back ordering
  232. ----------------------------------------------------------------------------------------*/
  233.  
  234. void    ZWindowManager::ShowWindow( ZWindow* aWindow )
  235. {
  236.     FailNILParam( aWindow );
  237.     
  238.     ShowHide( aWindow->GetMacWindow(), TRUE );
  239.     
  240.     if ( aWindow == GetTopWindow() ||
  241.          aWindow == GetTopFloater())
  242.         SelectWindow( aWindow );
  243. }
  244.  
  245.  
  246. /*--------------------------------***  SELECTWINDOW  ***--------------------------------*/
  247. /*    
  248. make the window active. This handles the front-to-back ordering and creates the "floating"
  249. window illusion.
  250. ----------------------------------------------------------------------------------------*/
  251.  
  252. void    ZWindowManager::SelectWindow( ZWindow* aWindow )
  253. {
  254.     FailNILParam( aWindow );
  255.     
  256.     // this is where a certain amount of cunning comes in. To "Select" a non-floater, it
  257.     // is actually moved to come behind the bottom floater. Floaters are treated normally.
  258.     // Dialogs can come in front of all windows, though they will be set to non-floating.
  259.     
  260.     ZWindow*    zw;
  261.     long        i;
  262.     
  263.     // if window is not visible, make it so
  264.     
  265.     if (! aWindow->IsVisible())
  266.         ShowHide( aWindow->GetMacWindow(), TRUE );
  267.         
  268.     // manipulate our lists and the mac window list
  269.     
  270.     if ( aWindow->Floats())
  271.     {
  272.         i = floaters->FindIndex( aWindow );
  273.         
  274.         // move to head of list, if not there already
  275.         
  276.         if ( i > 1 )
  277.         {
  278.             // deactivate current "top"
  279.             
  280.             zw = GetTopFloater();
  281.             
  282.             if ( zw )
  283.             {
  284.                 #ifndef _ALL_FLOATERS_ACTIVE
  285.                 HiliteWindow( zw->GetMacWindow(), FALSE );
  286.                 #endif
  287.                 
  288.                 zw->Deactivate();
  289.             }
  290.             
  291.             floaters->MoveToFront( i );
  292.             BringBehind( aWindow, NULL );
  293.         }    
  294.         // hilite and activate the new "top" window
  295.         
  296.         aWindow->Activate();
  297.         HiliteWindow( aWindow->GetMacWindow(), TRUE );
  298.     }
  299.     else
  300.     {
  301.         i = nonFloaters->FindIndex( aWindow );
  302.         
  303.         // if already on top, do nothing
  304.         
  305.         if ( i > 1 )
  306.         {
  307.             // deactivate the current "top"
  308.             
  309.             zw = GetTopWindow();
  310.             
  311.             if ( zw )
  312.                 PostActivation( zw, FALSE );
  313.             
  314.             // move to head of list
  315.             
  316.             nonFloaters->MoveToFront( i );
  317.         }    
  318.         // bring window behind the bottom floater, unless it's a dialog, in which
  319.         // case it's put on top of everything
  320.  
  321.         if ( IsDialog( aWindow ))
  322.         {
  323.             Deactivate();
  324.             BringBehind( aWindow, NULL );
  325.         }
  326.         else
  327.         {
  328.             zw = GetBottomFloater();
  329.             BringBehind( aWindow, zw );
  330.         }
  331.         
  332.         // hilite and activate the new "top" window
  333.         
  334.         PostActivation( aWindow, TRUE );
  335.     }
  336. }
  337.  
  338.  
  339. /*-----------------------------***  DRAGWINDOWOUTLINE  ***------------------------------*/
  340. /*    
  341. drag the outline of the window and move it when the mouse is released. This replaces the
  342. toolbox routine DragWindow, and in addition does a nicer job of clipping the outline.
  343. ----------------------------------------------------------------------------------------*/
  344.  
  345. void    ZWindowManager::DragWindowOutline( ZWindow* aWindow, Point startPt, const short modifiers )
  346. {
  347.     FailNILParam( aWindow );
  348.     
  349.     // replaces the toolbox DragWindow, because that will bring a window to the front if
  350.     // you let it.
  351.     
  352.     WindowPtr    w;
  353.     RgnHandle    dragRgn, temp = NULL;
  354.     Rect        limitRect;
  355.     long        dragOffset;
  356.     GrafPort    screenPort;
  357.     GrafPtr        savePort;
  358.     Point        wPosition;
  359.     
  360.     w = aWindow->GetMacWindow();
  361.     
  362.     // select the window if command key not down
  363.     
  364.     #ifndef _DRAGWINDOW_COMPATIBLE
  365.     
  366.     if (( modifiers & cmdKey ) == 0 &&
  367.         aWindow != GetTopWindow() &&
  368.         aWindow != GetTopFloater())
  369.     {
  370.         SelectWindow( aWindow );
  371.     
  372.         #ifdef _UPDATE_ON_SELECT
  373.         
  374.         ZEventHandler*    zEH = gApplication->GetEventHandler();
  375.         zEH->HandleWindowUpdate( w );
  376.         
  377.         #endif
  378.     }
  379.     
  380.     #endif
  381.     
  382.     // get the limit rect
  383.     
  384.     limitRect = (*GetGrayRgn())->rgnBBox;
  385.     InsetRect( &limitRect, 4, 4 );
  386.     
  387.     // get the outline to drag. This is simply a copy of the window's structure region
  388.     
  389.     FailNIL( dragRgn = NewRgn());
  390.     
  391.     CopyRgn(((WindowPeek) w)->strucRgn, dragRgn );
  392.     
  393.     // set up a port in which to drag the outline. We do this to be good citizens,
  394.     // since meddling with the Mac's Window Manager port is tricky to get away with.
  395.     
  396.     GetPort( &savePort );
  397.     OpenPort( &screenPort );
  398.     SetPort( &screenPort );
  399.     
  400.     // make sure we can drag on the whole desktop
  401.     
  402.     screenPort.portRect = (*GetGrayRgn())->rgnBBox;
  403.     SetClip( GetGrayRgn());
  404.     CopyRgn( screenPort.clipRgn, screenPort.visRgn );
  405.     
  406.     // Remove the regions of all windows in front from the clip region, so it is clearer
  407.     // what will happen when the window moves.
  408.     
  409.     FailNIL( temp = NewRgn());
  410.     CalcWindowRgns( aWindow, temp );
  411.     DiffRgn( screenPort.clipRgn, temp, screenPort.clipRgn );
  412.     
  413.     // drag the outline:
  414.         
  415.     dragOffset = DragGrayRgn( dragRgn, startPt, &limitRect, &limitRect, noConstraint, NULL );
  416.     
  417.     // delete our port
  418.     
  419.     ClosePort( &screenPort );
  420.     SetPort( savePort );
  421.     
  422.     // check the window drag wasn't bogus:
  423.     
  424.     if ( dragOffset != 0x80008000 )
  425.     {
  426.         // OK, figure out where the window moved to, and move it there. If the command key
  427.         // is not down, select tha' booga!
  428.         
  429.         SetPort( w );
  430.         
  431.         wPosition = topLeft( w->portRect );
  432.         LocalToGlobal( &wPosition );
  433.         SetPort( savePort );
  434.         
  435.         // if we are exactly compatible with toolbox DragWindow(), then select the window here
  436.         
  437.         #ifdef _DRAGWINDOW_COMPATIBLE
  438.         
  439.         if (( modifiers & cmdKey ) == 0 &&
  440.             aWindow != GetTopWindow() &&
  441.             aWindow != GetTopFloater())
  442.             SelectWindow( aWindow );
  443.         
  444.         #endif
  445.         
  446.         MoveWindow( w, wPosition.h + LoWord( dragOffset ), wPosition.v + HiWord( dragOffset ), FALSE );
  447.     }    
  448.     // clean up
  449.     
  450.     DisposeRgn( dragRgn );
  451.     
  452.     if ( temp )    
  453.         DisposeRgn( temp );
  454. }
  455.  
  456.  
  457. /*-----------------------------------***  SUSPEND  ***----------------------------------*/
  458. /*    
  459. application is suspending- hide the floaters
  460. ----------------------------------------------------------------------------------------*/
  461.  
  462. void    ZWindowManager::Suspend()
  463. {
  464.     // the application is being suspended, so all floaters should be hidden
  465.     
  466.     ZWindow*    aFloater;
  467.     ZWindow*    tw;
  468.     short        i;
  469.     
  470.     tw = GetTopWindow();
  471.     
  472.     if ( tw && !IsDialog( tw ))
  473.         Deactivate();    
  474.     
  475.     for (i = 1; i <= floaters->CountItems(); i++)
  476.     {
  477.         aFloater = floaters->GetObject( i );
  478.         
  479.         if ( aFloater )
  480.             ShowHideFloater( aFloater, TRUE );
  481.     }
  482.     
  483.     #ifndef _ACTIVATE_EVENTS_ARE_REAL
  484.     // actually send deactivate event to top window
  485.     
  486.     if ( tw )
  487.         PostActivation( tw, FALSE );
  488.     #endif
  489. }
  490.  
  491. /*-----------------------------------***  RESUME  ***-----------------------------------*/
  492. /*    
  493. application is resuming- show the floaters
  494. ----------------------------------------------------------------------------------------*/
  495.  
  496. void    ZWindowManager::Resume()
  497. {
  498.     // the application is being resumed, so all floaters should be re-shown.
  499.     
  500.     ZWindow*    aFloater;
  501.     ZWindow*    tw;
  502.     short        i;
  503.     
  504.     for (i = 1; i <= floaters->CountItems(); i++)
  505.     {
  506.         aFloater = floaters->GetObject( i );
  507.         
  508.         if ( aFloater )
  509.             ShowHideFloater( aFloater, FALSE );
  510.     }
  511.     
  512.     tw = GetTopWindow();
  513.     
  514.     if (tw && !IsDialog( tw ))
  515.         Activate();    
  516.     
  517.     #ifndef _ACTIVATE_EVENTS_ARE_REAL
  518.     // actually send activate event to top window
  519.     
  520.     if ( tw )
  521.         PostActivation( tw, TRUE );
  522.     #endif
  523. }
  524.  
  525. /*---------------------------------***  DEACTIVATE  ***---------------------------------*/
  526. /*    
  527. a modal dialog is coming up, so deactivate all floaters and the top window. You need to
  528. call this whenever you put up a non ZDialog-based dialog, such as standard file, for
  529. consistent behaviour with MacZoop dialogs. Those objects will call this automatically.
  530. ----------------------------------------------------------------------------------------*/
  531.  
  532. void    ZWindowManager::Deactivate()
  533. {
  534.     // a dialog is up, so all floaters plus the top window must be deactivated
  535.     
  536.     ZWindow*    zw;
  537.     
  538. #ifndef _ALL_FLOATERS_ACTIVE
  539.     
  540.     zw = GetTopFloater();
  541.     
  542.     if ( zw )
  543.         PostActivation( zw, FALSE );
  544.         
  545. #else
  546.     
  547.     short    i;
  548.     
  549.     for (i = 1; i <= floaters->CountItems(); i++ )
  550.     {
  551.         zw = floaters->GetObject( i );
  552.     
  553.         if ( zw )
  554.             PostActivation( zw, FALSE );
  555.     }
  556.     
  557. #endif
  558.     
  559.         
  560.     zw = GetTopWindow();
  561.     
  562.     if ( zw )
  563.         PostActivation( zw, FALSE );
  564. }
  565.  
  566.  
  567. /*----------------------------------***  ACTIVATE  ***----------------------------------*/
  568. /*    
  569. the modal dialog is going away, so reactivate the floaters and top window
  570. ----------------------------------------------------------------------------------------*/
  571.  
  572. void    ZWindowManager::Activate()
  573. {
  574.     // a dialog is going away, so all floaters plus the top window must be reactivated
  575.     
  576.     ZWindow*    zw;
  577.     
  578. #ifndef _ALL_FLOATERS_ACTIVE
  579.     
  580.     zw = GetTopFloater();
  581.     
  582.     if ( zw )
  583.         PostActivation( zw, TRUE );
  584.  
  585. #else
  586.     
  587.     short    i;
  588.     
  589.     for (i = 1; i <= floaters->CountItems(); i++ )
  590.     {
  591.         zw = floaters->GetObject( i );
  592.     
  593.         if ( zw )
  594.             PostActivation( zw, TRUE );
  595.     }
  596.     
  597. #endif
  598.     
  599.     zw = GetTopWindow();
  600.     
  601.     if ( zw && ! IsDialog( zw ))
  602.         PostActivation( zw, TRUE );
  603. }
  604.  
  605.  
  606. /*--------------------------------***  GETTOPWINDOW  ***--------------------------------*/
  607. /*    
  608. get uppermost non-floating window
  609. ----------------------------------------------------------------------------------------*/
  610.  
  611. ZWindow*    ZWindowManager::GetTopWindow()
  612. {
  613.     // returns the top non-floating window
  614.     
  615.     if ( nonFloaters->CountItems() > 0 )
  616.         return nonFloaters->GetObject( 1 );
  617.     else
  618.         return NULL;
  619. }
  620.  
  621.  
  622. /*-------------------------------***  GETTOPFLOATER  ***--------------------------------*/
  623. /*    
  624. get uppermost floating window
  625. ----------------------------------------------------------------------------------------*/
  626.  
  627. ZWindow*    ZWindowManager::GetTopFloater()
  628. {
  629.     // returns the top floating window
  630.     
  631.     if ( floaters->CountItems() > 0 )
  632.         return floaters->GetObject( 1 );
  633.     else
  634.         return NULL;
  635. }
  636.  
  637.  
  638. /*------------------------------***  GETBOTTOMFLOATER  ***------------------------------*/
  639. /*    
  640. get the last window in the floating layer. Top window is the one behind this.
  641. ----------------------------------------------------------------------------------------*/
  642.  
  643. ZWindow*    ZWindowManager::GetBottomFloater()
  644. {
  645.     // returns the bottom-most floater
  646.     
  647.     if ( floaters->CountItems() > 0 )
  648.         return floaters->GetObject( floaters->CountItems());
  649.     else
  650.         return NULL;    
  651. }
  652.  
  653.  
  654. /*------------------------------***  CHECKDIALOGEVENT  ***------------------------------*/
  655. /*    
  656. determine if the event is aimed at a dialog. This replaces the toolbox IsDialogEvent call
  657. such that it does not call FrontWindow().
  658. ----------------------------------------------------------------------------------------*/
  659.  
  660. Boolean        ZWindowManager::CheckDialogEvent( EventRecord* theEvent )
  661. {
  662.     // the event is for a dialog if the window kind explicitly passed with certain events is
  663.     // a dialog, or for other events, that the top window as we know it is a dialog.
  664.     
  665.     WindowPeek    w;
  666.     Boolean        result = FALSE;
  667.     ZWindow*    zw;
  668.     
  669.     // is this a window explicit event?
  670.     
  671.     if ( theEvent->what == updateEvt ||
  672.          theEvent->what == activateEvt )
  673.     {
  674.         // yes, so get the window and see if it's a dialog
  675.         
  676.         w = (WindowPeek) theEvent->message;
  677.     
  678.         result = ( w->windowKind == dialogKind );
  679.     }
  680.     else
  681.     {
  682.         // is the event a mouse down? If so we need to see if it was in the active dialog
  683.         // window.
  684.         
  685.         if ( theEvent->what == mouseDown )
  686.         {
  687.             short    part = FindWindow( theEvent->where, (WindowPtr*) &w );
  688.             
  689.             zw = GetTopWindow();
  690.             
  691.             result = (    part == inContent &&
  692.                         w->windowKind == dialogKind &&
  693.                         zw &&
  694.                         zw->GetMacWindow() == (WindowPtr) w );
  695.         }
  696.         else
  697.         {
  698.             zw = GetTopWindow();
  699.             
  700.             // we do our own checks but also call the toolbox IsDialogEvent, so that
  701.             // ballon help in dialogs is correctly displayed. (Balloon help hooks into
  702.             // this routine to provide dialog balloons).
  703.             
  704.             result = ( zw &&
  705.                        ((WindowPeek) zw->GetMacWindow())->windowKind == dialogKind &&
  706.                        IsDialogEvent( theEvent ));
  707.         }
  708.     }
  709.     return result;    
  710. }
  711.  
  712.  
  713. /*--------------------------------***  LOCATEWINDOW  ***--------------------------------*/
  714. /*    
  715. find the window under the mouse, or NULL if none are
  716. ----------------------------------------------------------------------------------------*/
  717.  
  718. ZWindow*    ZWindowManager::LocateWindow( const Point globalMouse )
  719. {
  720.     WindowPeek    w;
  721.     ZWindow*    zw = NULL;
  722.     
  723.     w = ( WindowPeek ) FrontWindow();
  724.     
  725.     while ( w )
  726.     {
  727.         if ( PtInRgn( globalMouse, w->strucRgn ))
  728.         {        
  729.             zw = GetZWindow(( WindowPtr ) w );
  730.             break;
  731.         }
  732.         
  733.         w = w->nextWindow;
  734.     }
  735.     
  736.     return zw;
  737. }
  738.  
  739.  
  740. /*--------------------------------***  GETNTHWINDOW  ***--------------------------------*/
  741. /*    
  742. return the window <n>, or NULL if bad index
  743. ----------------------------------------------------------------------------------------*/
  744.  
  745. ZWindow*    ZWindowManager::GetNthWindow( const long n )
  746. {
  747.     ZWindow*    zw = NULL;
  748.     
  749.     try
  750.     {
  751.         zw = nonFloaters->GetObject( n );
  752.     }
  753.     catch( OSErr err )
  754.     {
  755.     }
  756.     
  757.     return zw;
  758. }
  759.  
  760.  
  761. /*--------------------------------***  GETNTHFLOATER  ***-------------------------------*/
  762. /*    
  763. return the floating window <n>, or NULL if bad index
  764. ----------------------------------------------------------------------------------------*/
  765.  
  766. ZWindow*    ZWindowManager::GetNthFloater( const long n )
  767. {
  768.     ZWindow*    zw = NULL;
  769.     
  770.     try
  771.     {
  772.         zw = floaters->GetObject( n );
  773.     }
  774.     catch( OSErr err )
  775.     {
  776.     }
  777.     
  778.     return zw;
  779. }
  780.     
  781.  
  782. /*----------------------------------***  ISDIALOG  ***----------------------------------*/
  783. /*    
  784. is the window a modal dialog?
  785. ----------------------------------------------------------------------------------------*/
  786.  
  787. Boolean        ZWindowManager::IsDialog( ZWindow* aWindow )
  788. {
  789.     // return TRUE if the window is a modal dialog (but not for modeless ones)
  790.     
  791.     ZDialog*    zd = dynamic_cast<ZDialog*> ( aWindow );
  792.     
  793.     if (zd && zd->IsModal())
  794.         return TRUE;
  795.     else
  796.         return FALSE;
  797. }
  798.  
  799.  
  800. /*--------------------------***  GETUNIQUEUNTITLEDNAME  ***-----------------------------*/
  801. /*    
  802. as part of the human interface guidelines adherence, we automatically name new windows
  803. untitled, untitled 1, etc. This method scans through the names of all the windows in the
  804. main list (ignores floaters), making sure the name is unique. If not, it appends 1, 2, etc
  805. until the name is unique. If the name was unique, it returns FALSE, otherwise TRUE. i.e.
  806. TRUE means we modified the name. Uses EqualString to compare names, ignores case.
  807. ----------------------------------------------------------------------------------------*/
  808.  
  809. Boolean        ZWindowManager::GetUniqueUntitledName( Str255 wName )
  810. {
  811.     short        n = 1, i;
  812.     Boolean        result = FALSE, match;
  813.     Str255        sName, temp;
  814.     ZWindow*    zw;
  815.     
  816.     CopyPString( wName, temp );
  817.     
  818.     do
  819.     {
  820.         match = FALSE;
  821.         
  822.         for ( i = 1; i <= nonFloaters->CountItems(); i++ )
  823.         {    
  824.             zw = nonFloaters->GetObject( i );
  825.             zw->GetName( sName );
  826.             
  827.             if ( EqualString( temp, sName, FALSE, FALSE ))
  828.             {
  829.                 match = TRUE;
  830.                 break;
  831.             }
  832.         }
  833.         
  834.         if ( match )
  835.         {
  836.             // the name matched some window, so append a digit and try again
  837.         
  838.             CopyPString( wName, temp );
  839.             
  840.             NumToString( n++, sName );
  841.             ConcatPStrings( temp, "\p " );
  842.             ConcatPStrings( temp, sName );
  843.         }
  844.         else
  845.         {
  846.             result = TRUE;
  847.             CopyPString( temp, wName );
  848.         }
  849.     }
  850.     while( ! result );
  851.     
  852.     return result;    
  853. }
  854.  
  855.  
  856. /*----------------------------------***  FLOATIDLE  ***---------------------------------*/
  857. /*    
  858. pass idle to each floater, in case they do periodic action
  859. ----------------------------------------------------------------------------------------*/
  860.  
  861. void    ZWindowManager::FloatIdle()
  862. {
  863.     long        i;
  864.     ZWindow*    aFloater;
  865.     
  866.     for( i = 1; i <= floaters->CountItems(); i++ )
  867.     {
  868.         aFloater = floaters->GetObject( i );
  869.     
  870.         if ( aFloater )
  871.             aFloater->Idle();
  872.     }    
  873. }
  874.  
  875.  
  876. /*---------------------------------***  COUNTWINDOWS  ***-------------------------------*/
  877. /*    
  878. return the number of non-floating windows the manager knows about
  879. ----------------------------------------------------------------------------------------*/
  880.  
  881. short        ZWindowManager::CountWindows()
  882. {
  883.     return nonFloaters->CountItems();
  884. }
  885.  
  886. /*---------------------------------***  COUNTFLOATERS  ***------------------------------*/
  887. /*    
  888. return the number of floating windows the manager knows about
  889. ----------------------------------------------------------------------------------------*/
  890.  
  891. short        ZWindowManager::CountFloaters()
  892. {
  893.     return floaters->CountItems();
  894. }
  895.  
  896.  
  897. /*--------------------------------***  SETWINDOWSMENU  ***------------------------------*/
  898. /*    
  899. sets the passed menu to be the application's "Windows" menu. Called by ZMenuBar- do not
  900. call this method directly- use gMenuBar->NominateWindowsMenu() instead. This should be
  901. called before any non-floating windows are created.
  902. ----------------------------------------------------------------------------------------*/
  903.  
  904. void        ZWindowManager::SetWindowsMenu( MenuHandle aMenu )
  905. {
  906.     FailNILParam( aMenu );
  907.     
  908.     wmMenu = aMenu;
  909.     wmItemOffset = CountMenuItems( aMenu );
  910.     
  911.     // make a list to keep an ordered list of windows that does not depend on
  912.     // the front-to-back order
  913.     
  914.     FailNIL( wmWindows = new ZWindowList());
  915.     
  916.     BuildWindowsMenu();
  917. }
  918.  
  919.  
  920. /*-----------------------------***  SELECTWINDOWFROMMENU  ***---------------------------*/
  921. /*    
  922. called only by the main menubar to select the window from the menu. Do not call this
  923. yourself.
  924. ----------------------------------------------------------------------------------------*/
  925.  
  926. void        ZWindowManager::SelectWindowFromMenu( const short itemID )
  927. {
  928.     if ( wmMenu && wmWindows && !IsDialog( GetTopWindow()))
  929.     {
  930.         short    n = itemID - wmItemOffset;
  931.         
  932.         if ( wmItemOffset > 0 )
  933.             n--;    // allow for divider line
  934.         
  935.         if (( n > 0 ) && ( n <= wmWindows->CountItems()))
  936.         {
  937.             ZWindow*    zw = wmWindows->GetObject( n );
  938.         
  939.             if ( zw )
  940.                 zw->Select();
  941.         }
  942.     }
  943. }
  944.  
  945.  
  946. #pragma mark -
  947.  
  948. /*---------------------------------***  BRINGBEHIND  ***--------------------------------*/
  949. /*    
  950. change the window ordering so it is behind another. If behindWindow is NULL, window is
  951. brought to the front.
  952. ----------------------------------------------------------------------------------------*/
  953.  
  954. void        ZWindowManager::BringBehind( ZWindow* aWindow, ZWindow* behindWindow )
  955. {
  956.     // brings <aWindow> behind <behindWindow>. If <behindWindow> is NULL, it is brought
  957.     // to the front. This manipulates the mac windowlist to match the state here.
  958.     
  959.     WindowPtr    a, b;
  960.     
  961.     if ( behindWindow )
  962.     {
  963.         a = aWindow->GetMacWindow();
  964.         b = behindWindow->GetMacWindow();
  965.         
  966.         SendBehind( a, b );
  967.     }
  968.     else
  969.         BringToFront( aWindow->GetMacWindow()); 
  970. }
  971.  
  972.  
  973. /*-------------------------------***  POSTACTIVATION  ***-------------------------------*/
  974. /*    
  975. simulate an activation event for the window
  976. ----------------------------------------------------------------------------------------*/
  977.  
  978. void        ZWindowManager::PostActivation( ZWindow* aWindow, Boolean state )    
  979. {
  980.     // posts an activate event for the window. This will be picked up by the event handler, which
  981.     // will then maintain the command chain correctly. Floater activations are never sent in this
  982.     // way, but their activate methods are called directly.
  983.     
  984.     HiliteWindow( aWindow->GetMacWindow(), state );
  985.     
  986.     if ( aWindow->Floats())
  987.     {
  988.         if ( state )
  989.             aWindow->Activate();
  990.         else
  991.             aWindow->Deactivate();
  992.     }
  993.     else
  994.     {
  995.         
  996.         #ifdef _ACTIVATE_EVENTS_ARE_REAL
  997.         
  998.         EvQElPtr    evQ;
  999.         
  1000.         if ( aWindow )
  1001.         {
  1002.             long        evtMessage = (long) aWindow->GetMacWindow();
  1003.             
  1004.             FailOSErr( PPostEvent( activateEvt, evtMessage, &evQ ));
  1005.             
  1006.             // set up the modifiers to indicate activation state
  1007.             
  1008.             if ( state )
  1009.                 evQ->evtQModifiers |= activeFlag;
  1010.             else
  1011.                 evQ->evtQModifiers &= ~activeFlag;
  1012.         }
  1013.         
  1014.         #else
  1015.  
  1016.         ZEventHandler*    ze = gApplication->GetEventHandler();
  1017.         
  1018.         ze->HandleWindowActivate( aWindow->GetMacWindow(), state );
  1019.         
  1020.         #endif
  1021.     }
  1022. }
  1023.  
  1024.  
  1025. /*------------------------------***  CALCWIONDOWRGNS  ***-------------------------------*/
  1026. /*    
  1027. calculate the union of the window structure regions in front of the window. This is used
  1028. to build a clip region for window dragging.
  1029. ----------------------------------------------------------------------------------------*/
  1030.  
  1031. void    ZWindowManager::CalcWindowRgns( ZWindow* aWindow, RgnHandle aRgn )
  1032. {
  1033.     // sets <theRgn> to the union of all windows in front if <aWindow>, including floaters.
  1034.     // This is used to form the clip region for a window drag. Note- this doesn't check the
  1035.     // parameters for sanity.
  1036.     
  1037.     SetEmptyRgn( aRgn );
  1038.     
  1039.     // the simplest way to achieve this is to scan the real mac window list, since that
  1040.     // allows us to treat the window ordering simply without consideration of our separate
  1041.     // lists.
  1042.     
  1043.     WindowPeek    w = (WindowPeek) FrontWindow();
  1044.     
  1045.     while (w && w != (WindowPeek) aWindow->GetMacWindow())
  1046.     {
  1047.         UnionRgn( w->strucRgn, aRgn, aRgn );
  1048.     
  1049.         w = w->nextWindow;
  1050.     }
  1051. }
  1052.  
  1053.  
  1054. /*------------------------------***  SHOWHIDEFLOATER  ***-------------------------------*/
  1055. /*    
  1056. show or hide a floater by moving it offscreen.
  1057. ----------------------------------------------------------------------------------------*/
  1058.  
  1059. void    ZWindowManager::ShowHideFloater( ZWindow* aFloater, Boolean hide )
  1060. {
  1061.     FailNILParam( aFloater );
  1062.     
  1063.     short        dh = 10000;
  1064.     Point        wLoc;
  1065.     WindowPtr    w = aFloater->GetMacWindow();
  1066.     Rect        dtBounds  = (*GetGrayRgn())->rgnBBox;
  1067.     
  1068.     if (! hide)
  1069.         dh = -dh;
  1070.         
  1071.     wLoc = topLeft( w->portRect );
  1072.     
  1073.     aFloater->Focus();
  1074.     LocalToGlobal( &wLoc );
  1075.     
  1076.     // don't attempt to hide or show more than once- it doesn't work. To this end we check
  1077.     // that the window is not already positioned
  1078.     
  1079.     if (( hide && wLoc.h < dtBounds.right ) ||
  1080.         ( ! hide && wLoc.h > dtBounds.right ))
  1081.         MoveWindow( w, wLoc.h + dh, wLoc.v, FALSE );    
  1082. }
  1083.  
  1084.  
  1085. /*-----------------------------***  BUILDWINDOWSMENU  ***-------------------------------*/
  1086. /*    
  1087. fill menu with current list of windows, and check current one.
  1088. ----------------------------------------------------------------------------------------*/
  1089.  
  1090. void    ZWindowManager::BuildWindowsMenu()
  1091. {
  1092.     short    n, i, mi;
  1093.     
  1094.     if ( wmMenu )
  1095.     {
  1096.         // delete items beyond initial number
  1097.         
  1098.         n = CountMenuItems( wmMenu );
  1099.         
  1100.         while( n > wmItemOffset )
  1101.             DeleteMenuItem( wmMenu, n-- );
  1102.             
  1103.         // set menu to window titles. If the offset was >0, add a dividing line first
  1104.         
  1105.         if ( wmWindows )
  1106.         {    
  1107.             ZWindow*    zw;
  1108.             Str255        title;
  1109.             
  1110.             n = wmWindows->CountItems();
  1111.             
  1112.             if (( wmItemOffset > 0 ) && ( n > 0 ))
  1113.                 AppendMenu( wmMenu, "\p-" );
  1114.         
  1115.             for( i = 1; i <= n; i++ )
  1116.             {
  1117.                 mi = i + wmItemOffset;
  1118.                 
  1119.                 if ( wmItemOffset > 0 )
  1120.                     mi++;    // allow for extra divider line
  1121.                 
  1122.                 zw = wmWindows->GetObject( i );
  1123.                 
  1124.                 zw->GetName( title );
  1125.                 
  1126.                 AppendMenu( wmMenu, "\px" );
  1127.                 SetMenuItemText( wmMenu, mi, title );
  1128.                 EnableItem( wmMenu, mi );
  1129.                 
  1130.                 // if window is active, check that item
  1131.                 
  1132.                 if ( zw == GetTopWindow())
  1133.                     CheckItem( wmMenu, mi, TRUE );
  1134.             }
  1135.         }
  1136.     }
  1137. }
  1138.  
  1139.  
  1140.